﻿using Autofac;
using CNative.Cloud.CPlatform.EventBus.Events;
using CNative.Cloud.CPlatform.EventBus.Implementation;
using CNative.Cloud.CPlatform.Ioc;
using CNative.Cloud.CPlatform.Utilities;
using CNative.Cloud.Protocol.WS.Runtime;
using CNative.Cloud.ProxyGenerator;
using System;
using CNative.WebSocketCore.Server;
using System.Linq;
using CNative.Cloud.CPlatform.DependencyResolution;

namespace CNative.Cloud.Protocol.WS
{
   public abstract class WSBehavior : WebSocketBehavior, IServiceBehavior
    {
        #region CreateProxy
        public T CreateProxy<T>(string key) where T : class
        {
            //return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key);
            return GetService<T>(key);
        }
         
        public object CreateProxy(Type type)
        {
            //return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(type);
            return GetService(type);
        }

        public object CreateProxy(string key, Type type)
        {
            //return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(key, type);
            return GetService(key, type);
        }
         
        public T CreateProxy<T>() where T : class
        {
            //return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>();
            return GetService<T>();
        }
        #endregion
        #region GetService
        public T GetService<T>(string key) where T : class
        {
            if (ServiceLocator.Current.IsRegisteredWithKey<T>(key))
                return ServiceLocator.GetService<T>(key);
            else
            {
                var result = ServiceResolver.Current.GetService<T>(key);
                if (result == null)
                {
                    result = ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key);
                    ServiceResolver.Current.Register(key, result);
                }
                return result;
            }
        }

        public  T GetService<T>() where T : class
        {
            if (ServiceLocator.Current.IsRegistered<T>())
                return ServiceLocator.GetService<T>();
            else
            {
                var result = ServiceResolver.Current.GetService<T>();
                if (result == null)
                {
                    result = ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>();
                    ServiceResolver.Current.Register(null, result);
                }
                return result;
            }
        }

        public  object GetService(Type type)
        {
            if (ServiceLocator.Current.IsRegistered(type))
                return ServiceLocator.GetService(type);
            else
            {
                var result = ServiceResolver.Current.GetService(type);
                if (result == null)
                {
                    result = ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(type);
                    ServiceResolver.Current.Register(null, result);
                }
                return result;
            }
        }

        public object GetService(string key, Type type)
        {
            if (ServiceLocator.Current.IsRegisteredWithKey(key, type))
                return ServiceLocator.GetService(key, type);
            else
            {
                var result = ServiceResolver.Current.GetService(type, key);
                if (result == null)
                {
                    result = ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(key, type);
                    ServiceResolver.Current.Register(key, result);
                }
                return result;
            }

        }

        //public  T GetService<T>(string key) where T : class
        //{
        //    if (ServiceLocator.Current.IsRegisteredWithKey<T>(key))
        //        return ServiceLocator.GetService<T>(key);
        //    else
        //        return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>(key);
        //}

        //public   T GetService<T>() where T : class
        //{
        //    if (ServiceLocator.Current.IsRegistered<T>())
        //        return ServiceLocator.GetService<T>();
        //    else
        //        return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<T>();

        //}

        //public   object GetService(Type type)
        //{
        //    if (ServiceLocator.Current.IsRegistered(type))
        //        return ServiceLocator.GetService(type);
        //    else
        //        return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(type);
        //}

        //public   object GetService(string key, Type type)
        //{
        //    if (ServiceLocator.Current.IsRegisteredWithKey(key, type))
        //        return ServiceLocator.GetService(key, type);
        //    else
        //        return ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy(key, type);

        //}
        #endregion

        public WebSocketSessionManager GetClient()
        {
            WebSocketSessionManager result = null;
            var server = ServiceLocator.GetService<DefaultWSServerMessageListener>().Server;
            var entries = ServiceLocator.GetService<IWSServiceEntryProvider>().GetEntries();
            var entry = entries.Where(p => p.Type == this.GetType()).FirstOrDefault();
            if (server.WebSocketServices.TryGetServiceHost(entry.Path, out WebSocketServiceHostBase webSocketServiceHost))
                result = webSocketServiceHost.Sessions;
            return result;
        }

        public void Publish(IntegrationEvent @event)
        {
            GetService<IEventBus>().Publish(@event);
        }
    }
}
